﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;

namespace ExtractItAll.Core
{
  public class Password : IEquatable<Password>
  {
    public string Text { get; set; }
    public int Count { get; set; }

    #region IEquatable<Password> Member

    public bool Equals(Password other)
    {
      if (ReferenceEquals(null, other)) return false;
      if (ReferenceEquals(this, other)) return true;
      return other.Text.Equals(Text);
    }

    public override int GetHashCode()
    {
      return Text.GetHashCode();
    }

    #endregion
  }

  public class PasswordComparer : IComparer<Password>
  {
    #region IComparer<Password> Member

    public int Compare(Password x, Password y)
    {
      if (x.Count.Equals(y.Count))
        return String.Compare(x.Text, y.Text, System.StringComparison.Ordinal);
      else
        return y.Count.CompareTo(x.Count);
    }

    #endregion
  }

  /// <summary>
  /// A single task.
  /// </summary>
  public class PasswordList
  {
    private List<Password> _items = new List<Password>();
    private BindingList<Password> _items2 = new BindingList<Password>();

    public List<Password> Items
    {
      get { return _items; }
    }

    public int Pointer { get; private set; }

    public bool AllPasswordsChecked
    {
      get { return (Pointer >= Items.Count); }
    }

    public void Load(string path)
    {
      Items.Clear();

      if (!File.Exists(path))
        File.WriteAllText(path, String.Empty);

      string[] lines = File.ReadAllLines(path);

      Add(lines);
    }

    public void Save(string path)
    {
      StringBuilder text = new StringBuilder();
      StringBuilder textNoCount = new StringBuilder();

      foreach (Password password in Items)
      {
        text.AppendFormat("{1}\t{2}{0}", Environment.NewLine, password.Text, password.Count);
        textNoCount.AppendFormat("{1}{0}", Environment.NewLine, password.Text);
      }

      File.WriteAllText(path, text.ToString());
      File.WriteAllText(
        Path.GetDirectoryName(path) + "\\" +
        Path.GetFileNameWithoutExtension(path) + "_plain" +
        Path.GetExtension(path),
        textNoCount.ToString());
    }


    public void Add(string[] passwordList)
    {
      if (passwordList.Length == 0) return;

      foreach (string line in passwordList)
      {
        string[] str = line.Split('\t');
        Password password = new Password();


        switch (str.Length)
        {
          case 1:
            password.Text = str[0];

            if (password.Text.StartsWith("{\"") &&
                password.Text.EndsWith("\"}"))
            {
              foreach (string s in password.Text.Trim('{', '}').Split(','))
              {
                if (String.IsNullOrEmpty(s)) continue;
                Add(s.Trim('\"'));
              }
            }
            else
            {
              Add(password.Text);
            }
            break;

          case 2:
            password.Text = str[0];
            int itemp;
            password.Count = int.TryParse(str[1], out itemp) ? itemp : 0;

            Add(password.Text, password.Count);
            break;

          default:
            continue;
        }
      }

      Sort();
    }

    private void Add(string password, int counter = 0)
    {
      if (String.IsNullOrEmpty(password)) return;

      Password p = new Password();
      p.Text = password;
      p.Count = counter;

      if (Items.Contains(p))
        Items[Items.IndexOf(p)].Count += p.Count;
        //Items.Where(a => a.Equals(p)).First().Count += p.Count;
      else
        Items.Add(p);
    }

    //public void SetCounter(string password, int counter)
    //{
    //  Password pass = new Password();
    //  pass.Text = password;
    //  pass.Count = counter;

    //  if (Items.Contains(pass))
    //    Items[Items.IndexOf(pass)].Count = counter;

    //  Sort();
    //}

    //public void Remove(string password)
    //{
    //  Password pass = new Password();
    //  pass.Text = password;

    //  if (Items.Contains(pass))
    //    Items.RemoveAt(Items.IndexOf(pass));
    //}

    //public void Remove(string password)
    //{
    //  Password pass = new Password();
    //  pass.Text = password;

    //  if (Items.Contains(pass))
    //    Items.RemoveAt(Items.IndexOf(pass));
    //}

    public void Sort()
    {
      _items.Sort(new PasswordComparer());
    }


    public void Reset()
    {
      Pointer = 0;
    }

    public string GetNextPassword()
    {
      Pointer++;
      if (Pointer - 1 < Items.Count)
        return Items[Pointer - 1].Text;
      return null;
    }

    public void SetCorrectPassword(string text)
    {
      foreach (Password pw in Items.Where(pw => pw.Text == text))
      {
        pw.Count++;
        break;
      }

      Sort();
    }
  }
}